package finn.movingheadtracker;

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

public class MergedUniverse {
	final int id;
	int[] input;
	int[] output;
	
	public byte[] output_values = new byte[512];
	ChannelMergeMode[] cmm = new ChannelMergeMode[512];
	
	public MergedUniverse(final int id) {
		this.id = id;
	}
	
	@Override
	public String toString(){
		return String.valueOf(this.id);
	}
	
	/**
	 * Set The Universe Input of the Specified Universe
	 * @param universe_id The input Universe, in which the Values are changed
	 * @param values The new values
	 */
	public void setUniverseDmx(int universe_id, DmxValue[] values){
		List<DmxValue> new_values = new ArrayList<DmxValue>();
		if(Arrays.asList(input).contains(universe_id)){
			for(DmxValue value : values){
				if(Arrays.asList(cmm[value.addr].universes).contains(universe_id)){
					if(cmm[value.addr].type==ChannelMergeMode.HTP){
						boolean hasHigherValue = false;
						for(int new_universe_id : input){
							if(DmxMerger.getUniverse(new_universe_id).getChannelValue(value.addr) > value.value){
								hasHigherValue = true;
								break;
							}
						}
						if(!hasHigherValue){
							new_values.add(value);
						}
						
					}
					else{
						new_values.add(value);
					}
				}
			}
		}
		this.setOutputUniverseDmx((DmxValue[]) new_values.toArray());
	}
	
	/**
	 * Set all Output channels for the MergedUniverse and every Universe
	 * @param values
	 */
	private void setOutputUniverseDmx(DmxValue[] values){
		for(DmxValue value:values){
			this.output_values[value.addr] = value.value;
		}
		if (values.length == 0){
			return;
		}
		for(int un : output){
			DmxMerger.getUniverse(un).change(values);
		}
	}
	
	public byte[] getOutputUniverse(){
		return output_values;
	}
	
	public byte getMergingType(int channel){
		return cmm[channel].type;
	}
	
	public void setMergingType(byte type, int channel){
		cmm[channel].type = type;
	}
	
	public int[] getCMMInput(int channel){
		return cmm[channel].universes;
	}
	public void setCMMInput(int[] universes, int channel){
		cmm[channel].universes=universes;
	}
	public int[] getInput(){
		return this.input;
	}
	public void setInput(int[] inputs){
		this.input=inputs;
	}
	public int getValue(int channel){
		int[] ins = this.getCMMInput(channel);
		if(this.getMergingType(channel)==ChannelMergeMode.LTP){
			return output_values[channel];
		}
		int value = 0;
		for(int in:ins){
			if(value<DmxMerger.getUniverse(in).getChannelValue(channel)){
				value = DmxMerger.getUniverse(in).getChannelValue(channel);
			}
		}
		return value;
	}
	public int[] getOutput(){
		return this.output;
	}
	public byte[] getOutputValues(){
		return output_values;
	}
	public void setOutput(int[] outputs){
		this.output=outputs;
	}
	public class ChannelMergeMode{
		int[] universes;
		byte type;
		
		
		public static final byte HTP = 1;
		public static final byte LTP = 2;
		
		public boolean equals(ChannelMergeMode toCompare){
			Arrays.sort(this.universes);
			Arrays.sort(toCompare.universes);
			if(this.type != toCompare.type){
				return false;
			}
			if(toCompare.universes.length!= this.universes.length){
				return false;
			}
			for(int loop = 0; loop < this.universes.length; loop++){
				if(toCompare.universes[loop] != this.universes[loop]){
					return false;
				}
			}
			return true;
		}
	}
}
